package threadUtils.demo08;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 通过条件判断加Condition锁
 */
public class ConditionExample01 {

    private static int shareData = 0;
    private static boolean used = false;
    private static final Lock lock = new ReentrantLock();
    private static final Condition conditionLock = lock.newCondition();

    private static void change() {

        lock.lock(); // 给线程加锁，当前线程不释放锁，其他线程就拿不到主权限
        try {
            // 判断当前数据是否使用过，没使用过就进入等待，同时，进入finally释放当前线程锁。如果使用过，进行往后的逻辑
            if (!used) {
                conditionLock.await();
            }
            shareData++; // 数据变更
            used = false; // 变更之后的数据设置为未使用
            conditionLock.signal(); // 通知让一个等待的conditionLock线程苏醒
            System.out.println("Data has bean changed：" + shareData);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }

    private static void use() {

        lock.lock(); // 给线程加锁，当前线程不释放锁，其他线程就拿不到主权限
        try {
            // 如果数据使用过，不能再次使用，那么就进入等待状态，进入finally，释放当前线程。如果没有使用过数据，就进行之后的逻辑
            if (used) {
                conditionLock.await();
            }
            used = true; // 设置当前数据使用过
            conditionLock.signal(); // 发送信号，让一个等待的conditionLock线程苏醒
            System.out.println("Data has been used：" + shareData);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }


    }

    public static void main(String[] args) {

        new Thread(() -> {
            for(;;)
                change();
        }, "Produce").start();

        new Thread(() -> {
            for(;;)
                use();
        }, "Consumer").start();

    }
}
